# 高级搜索功能视图
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse, HttpResponse
from django.views.decorators.http import require_http_methods
from django.db.models import Q, Count, Sum, Avg, Max, Min
from django.core.paginator import Paginator
from django.utils import timezone
from datetime import datetime, timedelta
import json
import logging

from .models import Asset, AssetCategory, Department, MaintenanceRecord, AssetBorrow, Consumable, Supplier, Contract
from .models_system import SystemLog

logger = logging.getLogger(__name__)


class AdvancedSearchService:
    """高级搜索服务"""
    
    def __init__(self):
        self.search_models = {
            'assets': {
                'model': Asset,
                'fields': {
                    'name': {'type': 'text', 'label': '资产名称'},
                    'asset_number': {'type': 'text', 'label': '资产编号'},
                    'status': {'type': 'choice', 'label': '状态', 'choices': Asset.ASSET_STATUS_CHOICES},
                    'purchase_price': {'type': 'number', 'label': '购买价格'},
                    'purchase_date': {'type': 'date', 'label': '购买日期'},
                    'category__name': {'type': 'text', 'label': '类别'},
                    'department__name': {'type': 'text', 'label': '部门'},
                    'location__name': {'type': 'text', 'label': '位置'},
                    'supplier__name': {'type': 'text', 'label': '供应商'},
                }
            },
            'maintenance': {
                'model': MaintenanceRecord,
                'fields': {
                    'asset__name': {'type': 'text', 'label': '资产名称'},
                    'maintenance_type': {'type': 'choice', 'label': '维修类型', 'choices': MaintenanceRecord.MAINTENANCE_TYPE_CHOICES},
                    'status': {'type': 'choice', 'label': '状态', 'choices': MaintenanceRecord.MAINTENANCE_STATUS_CHOICES},
                    'estimated_cost': {'type': 'number', 'label': '预估成本'},
                    'actual_cost': {'type': 'number', 'label': '实际成本'},
                    'created_at': {'type': 'date', 'label': '创建时间'},
                    'completed_at': {'type': 'date', 'label': '完成时间'},
                }
            },
            'consumables': {
                'model': Consumable,
                'fields': {
                    'name': {'type': 'text', 'label': '耗材名称'},
                    'quantity': {'type': 'number', 'label': '当前数量'},
                    'min_quantity': {'type': 'number', 'label': '最小库存'},
                    'unit_price': {'type': 'number', 'label': '单价'},
                    'warehouse__name': {'type': 'text', 'label': '仓库'},
                }
            },
            'suppliers': {
                'model': Supplier,
                'fields': {
                    'name': {'type': 'text', 'label': '供应商名称'},
                    'contact_person': {'type': 'text', 'label': '联系人'},
                    'phone': {'type': 'text', 'label': '电话'},
                    'email': {'type': 'text', 'label': '邮箱'},
                    'address': {'type': 'text', 'label': '地址'},
                    'is_preferred': {'type': 'boolean', 'label': '优选供应商'},
                    'is_blacklisted': {'type': 'boolean', 'label': '黑名单'},
                }
            },
            'contracts': {
                'model': Contract,
                'fields': {
                    'contract_number': {'type': 'text', 'label': '合同编号'},
                    'title': {'type': 'text', 'label': '合同标题'},
                    'supplier__name': {'type': 'text', 'label': '供应商'},
                    'contract_amount': {'type': 'number', 'label': '合同金额'},
                    'start_date': {'type': 'date', 'label': '开始日期'},
                    'end_date': {'type': 'date', 'label': '结束日期'},
                    'status': {'type': 'choice', 'label': '状态', 'choices': Contract.CONTRACT_STATUS_CHOICES},
                }
            }
        }
    
    def build_complex_query(self, model_name, search_params):
        """构建复杂查询条件"""
        if model_name not in self.search_models:
            return None
        
        model = self.search_models[model_name]['model']
        queryset = model.objects.all()
        
        # 处理搜索条件
        conditions = search_params.get('conditions', [])
        logic_operator = search_params.get('logic', 'AND')  # AND 或 OR
        
        if not conditions:
            return queryset
        
        # 构建Q对象
        q_objects = []
        
        for condition in conditions:
            field = condition.get('field')
            operator = condition.get('operator')
            value = condition.get('value')
            
            if not all([field, operator, value]):
                continue
            
            q_obj = self._build_q_object(field, operator, value)
            if q_obj:
                q_objects.append(q_obj)
        
        if not q_objects:
            return queryset
        
        # 组合Q对象
        if logic_operator == 'OR':
            combined_q = q_objects[0]
            for q_obj in q_objects[1:]:
                combined_q |= q_obj
        else:  # AND
            combined_q = q_objects[0]
            for q_obj in q_objects[1:]:
                combined_q &= q_obj
        
        return queryset.filter(combined_q)
    
    def _build_q_object(self, field, operator, value):
        """构建单个Q对象"""
        try:
            if operator == 'equals':
                return Q(**{field: value})
            elif operator == 'not_equals':
                return ~Q(**{field: value})
            elif operator == 'contains':
                return Q(**{f'{field}__icontains': value})
            elif operator == 'not_contains':
                return ~Q(**{f'{field}__icontains': value})
            elif operator == 'starts_with':
                return Q(**{f'{field}__istartswith': value})
            elif operator == 'ends_with':
                return Q(**{f'{field}__iendswith': value})
            elif operator == 'gt':
                return Q(**{f'{field}__gt': value})
            elif operator == 'gte':
                return Q(**{f'{field}__gte': value})
            elif operator == 'lt':
                return Q(**{f'{field}__lt': value})
            elif operator == 'lte':
                return Q(**{f'{field}__lte': value})
            elif operator == 'between':
                if isinstance(value, list) and len(value) == 2:
                    return Q(**{f'{field}__range': value})
            elif operator == 'in':
                if isinstance(value, list):
                    return Q(**{f'{field}__in': value})
            elif operator == 'is_null':
                return Q(**{f'{field}__isnull': True})
            elif operator == 'is_not_null':
                return Q(**{f'{field}__isnull': False})
            elif operator == 'date_range':
                if isinstance(value, dict) and 'start' in value and 'end' in value:
                    return Q(**{f'{field}__range': [value['start'], value['end']]})
        except Exception as e:
            logger.error(f"构建Q对象时出错: {e}")
            return None
        
        return None
    
    def save_search_history(self, user, search_params):
        """保存搜索历史"""
        try:
            from .models_search import SearchHistory
            
            SearchHistory.objects.create(
                user=user,
                search_type=search_params.get('model'),
                search_params=search_params,
                search_name=search_params.get('name', f"搜索_{timezone.now().strftime('%Y%m%d_%H%M%S')}")
            )
        except Exception as e:
            logger.error(f"保存搜索历史时出错: {e}")
    
    def get_search_history(self, user, limit=10):
        """获取搜索历史"""
        try:
            from .models_search import SearchHistory
            
            return SearchHistory.objects.filter(
                user=user
            ).order_by('-created_at')[:limit]
        except Exception as e:
            logger.error(f"获取搜索历史时出错: {e}")
            return []


# 全局搜索服务实例
advanced_search_service = AdvancedSearchService()


@login_required
def advanced_search(request):
    """高级搜索页面"""
    # 获取可用的搜索模型
    search_models = advanced_search_service.search_models
    
    # 获取搜索历史
    search_history = advanced_search_service.get_search_history(request.user)
    
    context = {
        'search_models': search_models,
        'search_history': search_history,
        'operators': [
            {'value': 'equals', 'label': '等于'},
            {'value': 'not_equals', 'label': '不等于'},
            {'value': 'contains', 'label': '包含'},
            {'value': 'not_contains', 'label': '不包含'},
            {'value': 'starts_with', 'label': '开始于'},
            {'value': 'ends_with', 'label': '结束于'},
            {'value': 'gt', 'label': '大于'},
            {'value': 'gte', 'label': '大于等于'},
            {'value': 'lt', 'label': '小于'},
            {'value': 'lte', 'label': '小于等于'},
            {'value': 'between', 'label': '介于'},
            {'value': 'in', 'label': '在列表中'},
            {'value': 'is_null', 'label': '为空'},
            {'value': 'is_not_null', 'label': '不为空'},
            {'value': 'date_range', 'label': '日期范围'},
        ]
    }
    
    return render(request, 'assets/search/advanced_search.html', context)


@login_required
@require_http_methods(["POST"])
def execute_search(request):
    """执行搜索"""
    try:
        data = json.loads(request.body)
        model_name = data.get('model')
        search_params = data.get('params', {})
        save_history = data.get('save_history', False)
        
        # 执行搜索
        queryset = advanced_search_service.build_complex_query(model_name, search_params)
        
        if queryset is None:
            return JsonResponse({
                'success': False,
                'message': '无效的搜索模型'
            }, status=400)
        
        # 分页
        page = int(data.get('page', 1))
        page_size = int(data.get('page_size', 20))
        
        paginator = Paginator(queryset, page_size)
        page_obj = paginator.get_page(page)
        
        # 序列化结果
        results = []
        for obj in page_obj:
            result = {
                'id': obj.id,
                'display_name': str(obj),
                'detail_url': f'/assets/{model_name}/{obj.id}/',
            }
            
            # 添加模型特定字段
            if model_name == 'assets':
                result.update({
                    'name': obj.name,
                    'asset_number': obj.asset_number,
                    'status': obj.get_status_display(),
                    'category': obj.category.name if obj.category else '',
                    'department': obj.department.name if obj.department else '',
                    'purchase_price': float(obj.purchase_price or 0),
                })
            elif model_name == 'maintenance':
                result.update({
                    'asset_name': obj.asset.name,
                    'maintenance_type': obj.get_maintenance_type_display(),
                    'status': obj.get_status_display(),
                    'actual_cost': float(obj.actual_cost or 0),
                    'created_at': obj.created_at.strftime('%Y-%m-%d'),
                })
            elif model_name == 'consumables':
                result.update({
                    'name': obj.name,
                    'quantity': obj.quantity,
                    'min_quantity': obj.min_quantity,
                    'unit_price': float(obj.unit_price or 0),
                    'warehouse': obj.warehouse.name if obj.warehouse else '',
                })
            
            results.append(result)
        
        # 保存搜索历史
        if save_history:
            advanced_search_service.save_search_history(request.user, {
                'model': model_name,
                'params': search_params,
                'name': data.get('search_name', '')
            })
        
        return JsonResponse({
            'success': True,
            'results': results,
            'pagination': {
                'current_page': page_obj.number,
                'total_pages': paginator.num_pages,
                'total_count': paginator.count,
                'has_previous': page_obj.has_previous(),
                'has_next': page_obj.has_next(),
            }
        })
        
    except Exception as e:
        logger.error(f"执行搜索时出错: {e}")
        return JsonResponse({
            'success': False,
            'message': f'搜索失败: {str(e)}'
        }, status=500)


@login_required
@require_http_methods(["GET"])
def get_model_fields(request, model_name):
    """获取模型字段信息"""
    try:
        if model_name not in advanced_search_service.search_models:
            return JsonResponse({
                'success': False,
                'message': '无效的模型名称'
            }, status=400)
        
        fields = advanced_search_service.search_models[model_name]['fields']
        
        return JsonResponse({
            'success': True,
            'fields': fields
        })
        
    except Exception as e:
        logger.error(f"获取模型字段时出错: {e}")
        return JsonResponse({
            'success': False,
            'message': str(e)
        }, status=500)


@login_required
@require_http_methods(["POST"])
def save_search_template(request):
    """保存搜索模板"""
    try:
        data = json.loads(request.body)
        
        from .models_search import SearchTemplate
        
        template = SearchTemplate.objects.create(
            user=request.user,
            name=data.get('name'),
            description=data.get('description', ''),
            search_type=data.get('model'),
            search_params=data.get('params'),
            is_public=data.get('is_public', False)
        )
        
        return JsonResponse({
            'success': True,
            'message': '搜索模板保存成功',
            'template_id': template.id
        })
        
    except Exception as e:
        logger.error(f"保存搜索模板时出错: {e}")
        return JsonResponse({
            'success': False,
            'message': f'保存失败: {str(e)}'
        }, status=500)


@login_required
def search_templates(request):
    """搜索模板列表"""
    try:
        from .models_search import SearchTemplate
        
        templates = SearchTemplate.objects.filter(
            Q(user=request.user) | Q(is_public=True)
        ).order_by('-created_at')
        
        # 分页
        paginator = Paginator(templates, 20)
        page_number = request.GET.get('page')
        page_obj = paginator.get_page(page_number)
        
        context = {
            'page_obj': page_obj
        }
        
        return render(request, 'assets/search/search_templates.html', context)
        
    except Exception as e:
        logger.error(f"获取搜索模板时出错: {e}")
        return render(request, 'assets/search/search_templates.html', {'page_obj': None})


@login_required
@require_http_methods(["POST"])
def export_search_results(request):
    """导出搜索结果"""
    try:
        data = json.loads(request.body)
        model_name = data.get('model')
        search_params = data.get('params', {})
        export_format = data.get('format', 'excel')  # excel, csv, pdf
        
        # 执行搜索
        queryset = advanced_search_service.build_complex_query(model_name, search_params)
        
        if queryset is None:
            return JsonResponse({
                'success': False,
                'message': '无效的搜索模型'
            }, status=400)
        
        # 根据格式导出
        if export_format == 'excel':
            return export_to_excel(queryset, model_name)
        elif export_format == 'csv':
            return export_to_csv(queryset, model_name)
        elif export_format == 'pdf':
            return export_to_pdf(queryset, model_name)
        else:
            return JsonResponse({
                'success': False,
                'message': '不支持的导出格式'
            }, status=400)
        
    except Exception as e:
        logger.error(f"导出搜索结果时出错: {e}")
        return JsonResponse({
            'success': False,
            'message': f'导出失败: {str(e)}'
        }, status=500)


def export_to_excel(queryset, model_name):
    """导出到Excel"""
    import openpyxl
    from io import BytesIO
    
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.title = f"{model_name}_search_results"
    
    # 根据模型类型设置表头
    if model_name == 'assets':
        headers = ['资产名称', '资产编号', '状态', '类别', '部门', '购买价格', '购买日期']
        ws.append(headers)
        
        for asset in queryset:
            ws.append([
                asset.name,
                asset.asset_number,
                asset.get_status_display(),
                asset.category.name if asset.category else '',
                asset.department.name if asset.department else '',
                float(asset.purchase_price or 0),
                asset.purchase_date.strftime('%Y-%m-%d') if asset.purchase_date else ''
            ])
    
    # 保存到内存
    output = BytesIO()
    wb.save(output)
    output.seek(0)
    
    # 返回响应
    response = HttpResponse(
        output.getvalue(),
        content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    )
    response['Content-Disposition'] = f'attachment; filename="{model_name}_search_results_{timezone.now().strftime("%Y%m%d")}.xlsx"'
    
    return response


def export_to_csv(queryset, model_name):
    """导出到CSV"""
    import csv
    from io import StringIO
    
    output = StringIO()
    writer = csv.writer(output)
    
    # 根据模型类型设置表头和数据
    if model_name == 'assets':
        writer.writerow(['资产名称', '资产编号', '状态', '类别', '部门', '购买价格', '购买日期'])
        
        for asset in queryset:
            writer.writerow([
                asset.name,
                asset.asset_number,
                asset.get_status_display(),
                asset.category.name if asset.category else '',
                asset.department.name if asset.department else '',
                float(asset.purchase_price or 0),
                asset.purchase_date.strftime('%Y-%m-%d') if asset.purchase_date else ''
            ])
    
    # 返回响应
    response = HttpResponse(output.getvalue(), content_type='text/csv; charset=utf-8')
    response['Content-Disposition'] = f'attachment; filename="{model_name}_search_results_{timezone.now().strftime("%Y%m%d")}.csv"'
    
    return response


def export_to_pdf(queryset, model_name):
    """导出到PDF"""
    # 这里可以使用reportlab或其他PDF库
    # 暂时返回JSON响应
    return JsonResponse({
        'success': False,
        'message': 'PDF导出功能正在开发中'
    })